<?php


namespace EchoPHP\Facades;


abstract class Facade {
    /**
     * 应用程序实例
     * @var
     */
    protected static $app;

    /**
     * 已构建门面实例
     * @var array
     */
    protected static $builtInstances = [];

    /**
     * 获取facade实例
     * @return mixed
     */
    public static function getFacadeInstance() {
        $facadeClass = static::getFacadeClass();
        return static::buildFacadeInstance($facadeClass);
    }

    /**
     * 获取当前facade对应类名或者是已绑定容器的对象标识
     */
    protected abstract static function getFacadeClass();

    /**
     * 创建facade实例
     * @param $name     类名或标识
     * @param array $params 构造实例时用到的参数
     * @return mixed
     */
    protected static function buildFacadeInstance($name, $params = []) {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$builtInstances[$name])) {
            return static::$builtInstances[$name];
        }
        return static::$builtInstances[$name] = static::$app->make($name, $params);
    }

    /**
     * 单个删除已构建的facade实例
     * @param $name
     */
    public static function clearBuiltFacadeInstance($name) {
        unset(static::$builtInstances[$name]);
    }

    /**
     * 清除所有已经构建的facade实例
     */
    public static function clearBuiltFacadeInstances() {
        static::$builtInstances = [];
    }

    /**
     * 获取facade用的应用容器实例
     * @return mixed
     */
    public static function getFacadeApplication() {
        return static::$app;
    }

    /**
     * 设置facade用的应用容器实例
     * @param $app
     */
    public static function setFacadeApplication($app) {
        static::$app = $app;
    }

    /**
     * 使用静态调用魔术方法实现调用facade实例中得具体方法
     * @param $method
     * @param $params
     * @return mixed
     */
    public static function __callStatic($method, $params) {
        $facadeInstance = static::getFacadeInstance();
        return call_user_func_array([$facadeInstance, $method], $params);
    }
}